package com.xiaoshuidi.cloud.module.finance.dal.mysql.finance;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.mybatis.core.mapper.BaseMapperX;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.flow.FinanceFlowMoneyVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.flow.FinanceMoneyFlowPageReqVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.flow.FinanceOrderFeeVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.reconciliation.FinanceReconciliationFlowExcelVO;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceMoneyFlowDO;
import com.xiaoshuidi.cloud.module.finance.enums.finance.PaymentSourceEnum;
import com.xiaoshuidi.cloud.module.finance.enums.order.FinanceCommonStatusEnum;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Mapper
public interface FinanceMoneyFlowMapper extends BaseMapperX<FinanceMoneyFlowDO> {
    default int updateStatusByPayOrderIdAndStatus(Long payOrderId, String status, FinanceMoneyFlowDO update) {
        return update(update, new QueryWrapper<FinanceMoneyFlowDO>()
                .eq("pay_order_id", payOrderId).eq("status", status));
    }

    default PageResult<FinanceMoneyFlowDO> selectPage(FinanceMoneyFlowPageReqVO reqVO) {
        return selectPage(reqVO, wrapperQuery(reqVO)
                .and(StringUtils.hasText(reqVO.getKeyword()), wp -> wp.like("operator", reqVO.getKeyword())
                        .or()
                        .like("trader", reqVO.getKeyword())
                        .or()
                        .like("room_name", reqVO.getKeyword()))
                .eq("status", FinanceCommonStatusEnum.SUCCESS.name())
                .orderByDesc("id"));
    }

    default List<Map<String, Object>> selectSummary(FinanceMoneyFlowPageReqVO reqVO) {
        return selectMaps(wrapperQuery(reqVO)
                .and(StringUtils.hasText(reqVO.getKeyword()), wp -> wp.like("operator", reqVO.getKeyword())
                        .or()
                        .like("trader", reqVO.getKeyword())
                        .or()
                        .like("room_name", reqVO.getKeyword()))
                .eq("status", FinanceCommonStatusEnum.SUCCESS.name())
                .select("direction", "sum(trade_amount-discount) as tradeAmount")
                .groupBy("direction"));
    }

    default QueryWrapper<FinanceMoneyFlowDO> wrapperQuery(FinanceMoneyFlowPageReqVO reqVO) {
        QueryWrapper<FinanceMoneyFlowDO> wrapper = new QueryWrapper<FinanceMoneyFlowDO>()
                .in(reqVO.getApartmentId() != null && reqVO.getApartmentId().length > 0, "apartment_id", reqVO.getApartmentId())
                .eq(StringUtils.hasText(reqVO.getTrader()), "trader", reqVO.getTrader())
                .eq(reqVO.getDirection() != null, "direction", reqVO.getDirection())
                .in(reqVO.getPayMethod() != null && reqVO.getPayMethod().length > 0, "pay_method", reqVO.getPayMethod())
                .eq(StringUtils.hasText(reqVO.getOperator()), "operator", reqVO.getOperator())
                .eq(reqVO.getSubject() != null, "subject", reqVO.getSubject())
                .eq(StringUtils.hasText(reqVO.getSourceFrom()), "source_from", reqVO.getSourceFrom())
                .eq(StringUtils.hasText(reqVO.getSourceBizId()), "source_biz_id", reqVO.getSourceBizId())
                .eq(StringUtils.hasText(reqVO.getSourceBizType()), "source_biz_type", reqVO.getSourceBizId());
        if (reqVO.getTradeTime() != null && reqVO.getTradeTime().length > 1) {
            wrapper.between(reqVO.getTradeTime() != null && reqVO.getTradeTime().length > 1, "trade_time", reqVO.getTradeTime()[0], reqVO.getTradeTime()[1]);
        }
        if (reqVO.getPayTime() != null && reqVO.getPayTime().length > 1) {
            wrapper.between(reqVO.getPayTime() != null && reqVO.getPayTime().length > 1, "pay_time", reqVO.getPayTime()[0], reqVO.getPayTime()[1]);
        }
        return wrapper;
    }

    default List<Map<String, Object>> selectConfirmSummary(FinanceMoneyFlowPageReqVO reqVO) {
        return selectMaps(wrapperQuery(reqVO)
                .and(StringUtils.hasText(reqVO.getKeyword()), wp ->
                        wp.like("trade_no", reqVO.getKeyword())
                                .or()
                                .like("renter", reqVO.getKeyword())
                                .or()
                                .like("rent_customer", reqVO.getKeyword())
                                .or()
                                .like("trader", reqVO.getKeyword())
                                .or()
                                .like("operator", reqVO.getKeyword()))
                .eq("source_from", PaymentSourceEnum.OFFLINE.name())
                .select("status", "sum(trade_amount) as tradeAmount")
                .groupBy("status"));
    }

    default PageResult<FinanceMoneyFlowDO> selectConfirmPage(FinanceMoneyFlowPageReqVO reqVO) {
        return selectPage(reqVO, wrapperQuery(reqVO)
                .and(StringUtils.hasText(reqVO.getKeyword()), wp ->
                        wp.like("trade_no", reqVO.getKeyword())
                                .or()
                        .like("renter", reqVO.getKeyword())
                                .or()
                        .like("rent_customer", reqVO.getKeyword())
                                .or()
                        .like("trader", reqVO.getKeyword())
                                .or()
                        .like("operator", reqVO.getKeyword()))
                .eq(StringUtils.hasText(reqVO.getStatus()), "status", reqVO.getStatus())
                .eq("source_from", PaymentSourceEnum.OFFLINE.name())
                .orderByDesc("id"));
    }

    default List<Map<String, Object>> selectReconciliationSummary(FinanceMoneyFlowPageReqVO reqVO) {
        return selectMaps(wrapperQuery(reqVO)
                .and(StringUtils.hasText(reqVO.getKeyword()), wp -> wp.like("operator", reqVO.getKeyword())
                .or()
                .like("trader", reqVO.getKeyword())
                .or()
                .like("room_name", reqVO.getKeyword()))
                .eq("status", FinanceCommonStatusEnum.SUCCESS.name())
                .select(
                        "count(*) as totalCount",
                        "ifnull(sum(if(direction = 0, 1, 0)), 0) as totalIncomeCount",
                        "ifnull(sum(if(direction = 0, (trade_amount-discount),0)),0) as totalIncomeAmount",
                        "ifnull(sum(if(direction = 1, 1, 0)),0) as totalPayoutCount",
                        "ifnull(sum(if(direction = 1, (trade_amount-discount),0)),0) as totalPayoutAmount",
                        "ifnull(sum(if(pay_method = '支付宝', 1, 0)),0) as totalAlipayCount",
                        "ifnull(sum(if(pay_method = '微信', 1, 0)),0) as totalWeixinCount"
                ));
    }

    default FinanceMoneyFlowDO getByFlowNo(String flowNo) {
        return selectOne("flow_no", flowNo);
    }

    BigDecimal sumTodayCashIncome(@Param("tenantId")Long tenantId,@Param("apartmentId")Long apartmentId);

    BigDecimal sumTodayIncome(@Param("tenantId")Long tenantId,@Param("apartmentId")Long apartmentId);

    BigDecimal sumTotalInCurrentMonth(@Param("tenantId")Long tenantId,@Param("apartmentId")Long apartmentId);

    BigDecimal sumTotalInCurrentYear(@Param("tenantId")Long tenantId,@Param("apartmentId")Long apartmentId);

    List<FinanceFlowMoneyVO> getFlowByOrderId(String orderNo);

    IPage<FinanceMoneyFlowDO> pageMoneyFlow(Page<FinanceMoneyFlowDO> page, @Param("param") FinanceMoneyFlowPageReqVO reqVO);

    List<FinanceReconciliationFlowExcelVO> getFlowExportList(@Param("param")FinanceMoneyFlowPageReqVO reqVO);

}
